home *** CD-ROM | disk | FTP | other *** search
/ Programming Windows (5th Edition) / Programming Windows, 5th ed. - Companion CD (097-0002183)(1999).iso / Chap09 / OwnDraw / OwnDraw.c next >
Encoding:
C/C++ Source or Header  |  1998-10-09  |  8.3 KB  |  233 lines

  1. /*---------------------------------------------
  2.    OWNDRAW.C -- Owner-Draw Button Demo Program
  3.                 (c) Charles Petzold, 1998
  4.   ---------------------------------------------*/
  5.  
  6. #include <windows.h>
  7.  
  8. #define ID_SMALLER      1
  9. #define ID_LARGER       2
  10.  
  11. #define BTN_WIDTH        (8 * cxChar)
  12. #define BTN_HEIGHT       (4 * cyChar)
  13.  
  14. LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
  15.  
  16. HINSTANCE hInst ;
  17.  
  18. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  19.                     PSTR szCmdLine, int iCmdShow)
  20. {
  21.      static TCHAR szAppName[] = TEXT ("OwnDraw") ;
  22.      MSG          msg ;
  23.      HWND         hwnd ;
  24.      WNDCLASS     wndclass ;
  25.      
  26.      hInst = hInstance ;
  27.      
  28.      wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
  29.      wndclass.lpfnWndProc   = WndProc ;
  30.      wndclass.cbClsExtra    = 0 ;
  31.      wndclass.cbWndExtra    = 0 ;
  32.      wndclass.hInstance     = hInstance ;
  33.      wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
  34.      wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  35.      wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
  36.      wndclass.lpszMenuName  = szAppName ;
  37.      wndclass.lpszClassName = szAppName ;
  38.      
  39.      if (!RegisterClass (&wndclass))
  40.      {
  41.           MessageBox (NULL, TEXT ("This program requires Windows NT!"),
  42.                       szAppName, MB_ICONERROR) ;
  43.           return 0 ;
  44.      }
  45.      
  46.      hwnd = CreateWindow (szAppName, TEXT ("Owner-Draw Button Demo"),
  47.                           WS_OVERLAPPEDWINDOW,
  48.                           CW_USEDEFAULT, CW_USEDEFAULT,
  49.                           CW_USEDEFAULT, CW_USEDEFAULT,
  50.                           NULL, NULL, hInstance, NULL) ;
  51.      
  52.      ShowWindow (hwnd, iCmdShow) ;
  53.      UpdateWindow (hwnd) ; 
  54.      
  55.      while (GetMessage (&msg, NULL, 0, 0))
  56.      {
  57.           TranslateMessage (&msg) ;
  58.           DispatchMessage (&msg) ;
  59.      }
  60.      return msg.wParam ;
  61. }
  62.  
  63. void Triangle (HDC hdc, POINT pt[])
  64. {
  65.      SelectObject (hdc, GetStockObject (BLACK_BRUSH)) ;
  66.      Polygon (hdc, pt, 3) ;
  67.      SelectObject (hdc, GetStockObject (WHITE_BRUSH)) ;
  68. }
  69.  
  70. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  71. {
  72.      static HWND      hwndSmaller, hwndLarger ;
  73.      static int       cxClient, cyClient, cxChar, cyChar ;
  74.      int              cx, cy ;
  75.      LPDRAWITEMSTRUCT pdis ;
  76.      POINT            pt[3] ;
  77.      RECT             rc ;
  78.      
  79.      switch (message)
  80.      {
  81.      case WM_CREATE :
  82.           cxChar = LOWORD (GetDialogBaseUnits ()) ;
  83.           cyChar = HIWORD (GetDialogBaseUnits ()) ;
  84.           
  85.                // Create the owner-draw pushbuttons
  86.           
  87.           hwndSmaller = CreateWindow (TEXT ("button"), TEXT (""),
  88.                                       WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
  89.                                       0, 0, BTN_WIDTH, BTN_HEIGHT,
  90.                                       hwnd, (HMENU) ID_SMALLER, hInst, NULL) ;
  91.           
  92.           hwndLarger  = CreateWindow (TEXT ("button"), TEXT (""),
  93.                                       WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
  94.                                       0, 0, BTN_WIDTH, BTN_HEIGHT,
  95.                                       hwnd, (HMENU) ID_LARGER, hInst, NULL) ;
  96.           return 0 ;
  97.           
  98.      case WM_SIZE :
  99.           cxClient = LOWORD (lParam) ;
  100.           cyClient = HIWORD (lParam) ;
  101.           
  102.                // Move the buttons to the new center
  103.           
  104.           MoveWindow (hwndSmaller, cxClient / 2 - 3 * BTN_WIDTH  / 2,
  105.                                    cyClient / 2 -     BTN_HEIGHT / 2,
  106.                       BTN_WIDTH, BTN_HEIGHT, TRUE) ;
  107.           
  108.           MoveWindow (hwndLarger,  cxClient / 2 +     BTN_WIDTH  / 2,
  109.                                    cyClient / 2 -     BTN_HEIGHT / 2,
  110.                       BTN_WIDTH, BTN_HEIGHT, TRUE) ;
  111.           return 0 ;
  112.           
  113.      case WM_COMMAND :
  114.           GetWindowRect (hwnd, &rc) ;
  115.           
  116.                // Make the window 10% smaller or larger
  117.           
  118.           switch (wParam)
  119.           {
  120.           case ID_SMALLER :
  121.                rc.left   += cxClient / 20 ;
  122.                rc.right  -= cxClient / 20 ;
  123.                rc.top    += cyClient / 20 ;
  124.                rc.bottom -= cyClient / 20 ;
  125.                break ;
  126.                
  127.           case ID_LARGER :
  128.                rc.left   -= cxClient / 20 ;
  129.                rc.right  += cxClient / 20 ;
  130.                rc.top    -= cyClient / 20 ;
  131.                rc.bottom += cyClient / 20 ;
  132.                break ;
  133.           }
  134.           
  135.           MoveWindow (hwnd, rc.left, rc.top, rc.right  - rc.left,
  136.                             rc.bottom - rc.top, TRUE) ;
  137.           return 0 ;
  138.           
  139.      case WM_DRAWITEM :
  140.           pdis = (LPDRAWITEMSTRUCT) lParam ;
  141.           
  142.                // Fill area with white and frame it black
  143.           
  144.           FillRect (pdis->hDC, &pdis->rcItem,
  145.                     (HBRUSH) GetStockObject (WHITE_BRUSH)) ;
  146.           
  147.           FrameRect (pdis->hDC, &pdis->rcItem,
  148.                      (HBRUSH) GetStockObject (BLACK_BRUSH)) ;
  149.           
  150.                // Draw inward and outward black triangles
  151.           
  152.           cx = pdis->rcItem.right  - pdis->rcItem.left ;
  153.           cy = pdis->rcItem.bottom - pdis->rcItem.top  ;
  154.           
  155.           switch (pdis->CtlID)
  156.           {
  157.           case ID_SMALLER :
  158.                pt[0].x = 3 * cx / 8 ;  pt[0].y = 1 * cy / 8 ;
  159.                pt[1].x = 5 * cx / 8 ;  pt[1].y = 1 * cy / 8 ;
  160.                pt[2].x = 4 * cx / 8 ;  pt[2].y = 3 * cy / 8 ;
  161.                
  162.                Triangle (pdis->hDC, pt) ;
  163.                
  164.                pt[0].x = 7 * cx / 8 ;  pt[0].y = 3 * cy / 8 ;
  165.                pt[1].x = 7 * cx / 8 ;  pt[1].y = 5 * cy / 8 ;
  166.                pt[2].x = 5 * cx / 8 ;  pt[2].y = 4 * cy / 8 ;
  167.                
  168.                Triangle (pdis->hDC, pt) ;
  169.                
  170.                pt[0].x = 5 * cx / 8 ;  pt[0].y = 7 * cy / 8 ;
  171.                pt[1].x = 3 * cx / 8 ;  pt[1].y = 7 * cy / 8 ;
  172.                pt[2].x = 4 * cx / 8 ;  pt[2].y = 5 * cy / 8 ;
  173.                
  174.                Triangle (pdis->hDC, pt) ;
  175.                
  176.                pt[0].x = 1 * cx / 8 ;  pt[0].y = 5 * cy / 8 ;
  177.                pt[1].x = 1 * cx / 8 ;  pt[1].y = 3 * cy / 8 ;
  178.                pt[2].x = 3 * cx / 8 ;  pt[2].y = 4 * cy / 8 ;
  179.                
  180.                Triangle (pdis->hDC, pt) ;
  181.                break ;
  182.                
  183.           case ID_LARGER :
  184.                pt[0].x = 5 * cx / 8 ;  pt[0].y = 3 * cy / 8 ;
  185.                pt[1].x = 3 * cx / 8 ;  pt[1].y = 3 * cy / 8 ;
  186.                pt[2].x = 4 * cx / 8 ;  pt[2].y = 1 * cy / 8 ;
  187.                
  188.                Triangle (pdis->hDC, pt) ;
  189.                
  190.                pt[0].x = 5 * cx / 8 ;  pt[0].y = 5 * cy / 8 ;
  191.                pt[1].x = 5 * cx / 8 ;  pt[1].y = 3 * cy / 8 ;
  192.                pt[2].x = 7 * cx / 8 ;  pt[2].y = 4 * cy / 8 ;
  193.                
  194.                Triangle (pdis->hDC, pt) ;
  195.                
  196.                pt[0].x = 3 * cx / 8 ;  pt[0].y = 5 * cy / 8 ;
  197.                pt[1].x = 5 * cx / 8 ;  pt[1].y = 5 * cy / 8 ;
  198.                pt[2].x = 4 * cx / 8 ;  pt[2].y = 7 * cy / 8 ;
  199.                
  200.                Triangle (pdis->hDC, pt) ;
  201.                
  202.                pt[0].x = 3 * cx / 8 ;  pt[0].y = 3 * cy / 8 ;
  203.                pt[1].x = 3 * cx / 8 ;  pt[1].y = 5 * cy / 8 ;
  204.                pt[2].x = 1 * cx / 8 ;  pt[2].y = 4 * cy / 8 ;
  205.                
  206.                Triangle (pdis->hDC, pt) ;
  207.                break ;
  208.           }
  209.           
  210.                // Invert the rectangle if the button is selected
  211.           
  212.           if (pdis->itemState & ODS_SELECTED)
  213.                InvertRect (pdis->hDC, &pdis->rcItem) ;
  214.           
  215.                // Draw a focus rectangle if the button has the focus
  216.           
  217.           if (pdis->itemState & ODS_FOCUS)
  218.           {
  219.                pdis->rcItem.left   += cx / 16 ;
  220.                pdis->rcItem.top    += cy / 16 ;
  221.                pdis->rcItem.right  -= cx / 16 ;
  222.                pdis->rcItem.bottom -= cy / 16 ;
  223.                
  224.                DrawFocusRect (pdis->hDC, &pdis->rcItem) ;
  225.           }
  226.           return 0 ;
  227.           
  228.      case WM_DESTROY :
  229.           PostQuitMessage (0) ;
  230.           return 0 ;
  231.      }
  232.      return DefWindowProc (hwnd, message, wParam, lParam) ;
  233. }